<template>
  <ms-container>
    <ms-aside-container>
      <div @click="showAll">

        <div class="tip">{{ $t('test_track.plan_view.base_info') }}</div>
        <el-form :model="currentScenario" label-position="right" label-width="80px" size="small" :rules="rules"
                 ref="currentScenario">
          <!-- 基础信息 -->
          <el-form-item :label="$t('commons.name')" prop="name">
            <el-input
              class="ms-scenario-input"
              size="small"
              v-model="currentScenario.name"
              maxlength="100"
              show-word-limit/>
          </el-form-item>

          <el-form-item :label="$t('test_track.module.module')" prop="apiScenarioModuleId">
            <ms-select-tree size="small" :data="moduleOptions" :defaultKey="currentScenario.apiScenarioModuleId"
                            @getValue="setModule" :obj="moduleObj" clearable checkStrictly/>
          </el-form-item>

          <el-form-item :label="$t('commons.status')" prop="status">
            <el-select class="ms-scenario-input" size="small" v-model="currentScenario.status">
              <el-option v-for="item in options" :key="item.id" :label="$t(item.label)" :value="item.id"/>
            </el-select>
          </el-form-item>

          <el-form-item :label="$t('api_test.definition.request.responsible')" prop="principal">
            <el-select v-model="currentScenario.principal"
                       :placeholder="$t('api_test.definition.request.responsible')" filterable size="small"
                       class="ms-scenario-input">
              <el-option
                v-for="item in maintainerOptions"
                :key="item.id"
                :label="item.name + ' (' + item.id + ')'"
                :value="item.id">
              </el-option>
            </el-select>
          </el-form-item>

          <el-form-item :label="$t('test_track.case.priority')" prop="level">
            <el-select class="ms-scenario-input" size="small" v-model="currentScenario.level">
              <el-option v-for="item in levels" :key="item.id" :label="item.label" :value="item.id"/>
            </el-select>
          </el-form-item>

          <el-form-item :label="$t('api_test.automation.tag')" prop="tags">
            <ms-input-tag :currentScenario="currentScenario" ref="tag"/>
          </el-form-item>

          <el-form-item :label="$t('commons.description')" prop="description">
            <el-input class="ms-http-textarea"
                      v-model="currentScenario.description"
                      type="textarea"
                      :autosize="{ minRows: 1, maxRows: 10}"
                      :rows="1" size="small"/>
          </el-form-item>
          <el-form-item label="ID" prop="customNum" v-if="customNum">
            <el-input v-model.trim="currentScenario.customNum" size="small"></el-input>
          </el-form-item>

        </el-form>
      </div>
    </ms-aside-container>

    <!-- 右侧部分 -->
    <ms-main-container style="overflow: hidden" class="ms-scenario-main-container">
      <!-- header 调试部分 -->
      <div class="ms-debug-div" @click="showAll" ref="debugHeader">
        <el-row style="margin: 5px">
          <el-col :span="1" class="ms-col-one ms-font" v-show="scenarioDefinition.length > 1">
            <el-tooltip :content="$t('test_track.case.batch_operate')" placement="top" effect="light"
                        v-show="!isBatchProcess">
              <font-awesome-icon class="ms-batch-btn" :icon="['fa', 'bars']" v-prevent-re-click
                                 @click="batchProcessing"/>
            </el-tooltip>
            <el-checkbox v-show="isBatchProcess" v-model="isCheckedAll" @change="checkedAll"/>
            <el-tooltip :content="$t('commons.cancel')" placement="top" effect="light" v-show="isBatchProcess">
              <font-awesome-icon class="ms-batch-btn" :icon="['fa', 'times']" v-prevent-re-click
                                 @click="cancelBatchProcessing"/>
            </el-tooltip>
          </el-col>
          <el-col :span="2" class="ms-col-one ms-font">
            {{ $t('api_test.automation.step_total') }}：{{ scenarioDefinition.length }}
          </el-col>
          <el-col :span="2" class="ms-col-one ms-font">
            <el-link class="head" @click="showScenarioParameters">{{ $t('api_test.automation.scenario_total') }}
            </el-link>
            ：{{ getVariableSize() }}
          </el-col>
          <el-col :span="2" class="ms-col-one ms-font">
            <el-checkbox v-model="enableCookieShare"><span
              style="font-size: 13px;">{{ $t('api_test.scenario.share_cookie') }}</span></el-checkbox>
          </el-col>
          <el-col :span="3" class="ms-col-one ms-font">
            <el-checkbox v-model="onSampleError"><span style="font-size: 13px;">{{
                $t('commons.failure_continues')
              }}</span></el-checkbox>
          </el-col>

          <el-col :span="13">
            <env-popover :disabled="scenarioDefinition.length < 1" :env-map="projectEnvMap"
                         :project-ids="projectIds" :result="envResult"
                         :environment-type.sync="environmentType" :isReadOnly="scenarioDefinition.length < 1"
                         :group-id="envGroupId" :project-list="projectList"
                         :show-config-button-with-out-permission="showConfigButtonWithOutPermission"
                         @setProjectEnvMap="setProjectEnvMap" @setEnvGroup="setEnvGroup"
                         @showPopover="showPopover" :has-option-group="true"
                         ref="envPopover" class="ms-message-right"/>
            <el-tooltip v-if="!debugLoading" content="Ctrl + R" placement="top">
              <el-dropdown split-button type="primary" @click="runDebug" class="ms-message-right" size="mini"
                           @command="handleCommand"
                           v-permission="['PROJECT_API_SCENARIO:READ+EDIT', 'PROJECT_API_SCENARIO:READ+CREATE', 'PROJECT_API_SCENARIO:READ+COPY']">
                {{ $t('api_test.request.debug') }}
                <el-dropdown-menu slot="dropdown">
                  <el-dropdown-item>{{ $t('api_test.automation.generate_report') }}</el-dropdown-item>
                </el-dropdown-menu>
              </el-dropdown>
            </el-tooltip>
            <el-button size="mini" type="primary" v-else @click="stop">{{ $t('report.stop_btn') }}</el-button>

            <el-button id="inputDelay" type="primary" size="mini" v-prevent-re-click @click="editScenario"
                       title="ctrl + s"
                       v-permission="['PROJECT_API_SCENARIO:READ+EDIT', 'PROJECT_API_SCENARIO:READ+CREATE', 'PROJECT_API_SCENARIO:READ+COPY']">
              {{ $t('commons.save') }}
            </el-button>

            <el-tooltip class="item" effect="dark" :content="$t('commons.refresh')" placement="top-start">
              <el-button :disabled="scenarioDefinition.length < 1" size="mini" icon="el-icon-refresh"
                         v-prevent-re-click @click="refreshApiScenario"></el-button>
            </el-tooltip>
            <!--操作按钮-->
            <el-link type="primary" @click.stop @click="showHistory" style="margin: 0px 5px">
              {{ $t("commons.debug_history") }}
            </el-link>

            <el-tooltip :content="$t('commons.follow')" placement="bottom" effect="dark" v-show="!showFollow">
              <i class="el-icon-star-off"
                 style="color: var(--primary_color); font-size: 22px; margin-right: 5px;cursor: pointer;position: relative; top: 3px; "
                 @click="saveFollow"/>
            </el-tooltip>
            <el-tooltip :content="$t('commons.cancel')" placement="bottom" effect="dark" v-show="showFollow">
              <i class="el-icon-star-on"
                 style="color: var(--primary_color); font-size: 22px; margin-right: 5px;cursor: pointer;position: relative; top: 3px; "
                 @click="saveFollow"/>
            </el-tooltip>
            <el-link type="primary" style="margin-right: 5px" @click="openHis"
                     v-show="path === '/api/automation/update'">{{ $t('operating_log.change_history') }}
            </el-link>
            <!--  版本历史 -->
            <ms-version-history v-xpack
                                ref="versionHistory"
                                :version-data="versionData"
                                :current-id="currentScenario.id"
                                @compare="compare" @checkout="checkout" @create="create" @del="del"/>
          </el-col>
          <el-tooltip effect="dark" :content="$t('commons.full_screen_editing')"
                      placement="top-start" style="margin-top: 6px">
            <font-awesome-icon class="alt-ico" :icon="['fa', 'expand-alt']" size="lg" @click="fullScreen"/>
          </el-tooltip>
        </el-row>
      </div>

      <div class="card-content">
        <!-- 场景步骤-->
        <div v-loading="loading">
          <el-row>
            <el-col :span="21">
              <div class="ms-debug-result" v-show="debug">
                <span class="ms-message-right"> {{ reqTotalTime }} ms </span>
                <span class="ms-message-right">{{ $t('api_test.automation.request_total') }} {{ reqTotal }}</span>
                <span class="ms-message-right">{{ $t('api_test.automation.request_success') }} {{ reqSuccess }}</span>
                <span class="ms-message-right"> {{ $t('api_test.automation.request_error') }} {{ reqError }}</span>
              </div>
            </el-col>
            <el-col></el-col>
          </el-row>
          <el-row>
            <el-col :span="21">
              <!-- 场景步骤内容 -->
              <div ref="stepInfo">
                <el-tree node-key="resourceId" :props="props" :data="scenarioDefinition" class="ms-tree"
                         :expand-on-click-node="false"
                         :allow-drop="allowDrop"
                         :empty-text="$t('api_test.scenario.step_info')"
                         highlight-current
                         :show-checkbox="isBatchProcess"
                         @check-change="chooseHeadsUp"
                         @node-drag-end="allowDrag" @node-click="nodeClick" draggable ref="stepTree" :key="reloadTree">

                  <el-row class="custom-tree-node" :gutter="10" type="flex" align="middle" slot-scope="{node, data}"
                          style="width: 100%">
                    <span class="custom-tree-node-col" style="padding-left:0px;padding-right:0px"
                          v-show="node && data.hashTree && data.hashTree.length > 0 && !data.isLeaf">
                      <span v-show="!node.expanded" class="el-icon-circle-plus-outline custom-node_e"
                            @click="openOrClose(node, data)"/>
                      <span v-show="node.expanded" class="el-icon-remove-outline custom-node_e"
                            @click="openOrClose(node, data)"/>
                    </span>
                    <!-- 批量操作 -->
                    <span :class="data.checkBox? 'custom-tree-node-hide' : 'custom-tree-node-col'"
                          style="padding-left: 0px; padding-right: 0px;"
                          v-show="(data.hashTree && data.hashTree.length === 0 )|| data.isLeaf">
                      <show-more-btn :is-show="node.checked" :buttons="batchOperators" :size="selectDataCounts"
                                     v-show="data.checkBox" style="margin-right: 10px"/>
                    </span>
                    <span style="width: calc(100% - 40px);">
                      <!-- 步骤组件-->
                      <ms-component-config
                        :scenario-definition="scenarioDefinition"
                        :message="message"
                        :type="data.type"
                        :scenario="data"
                        :response="response"
                        :currentScenario="currentScenario"
                        :node="node"
                        :project-list="projectList"
                        :env-map="projectEnvMap"
                        :env-group-id="envGroupId"
                        :environment-type="environmentType"
                        @remove="remove"
                        @copyRow="copyRow"
                        @suggestClick="suggestClick"
                        @refReload="refReload"
                        @runScenario="runDebug"
                        @stopScenario="stop"
                        @setDomain="setDomain"
                        @openScenario="openScenario"
                        @editScenarioAdvance="editScenarioAdvance"
                        ref="componentConfig"
                        v-if="stepFilter.get('ALlSamplerStep').indexOf(data.type) ===-1
                         || (!node.parent || !node.parent.data || stepFilter.get('AllSamplerProxy').indexOf(node.parent.data.type) === -1)"
                      />
                      <div v-else class="el-tree-node is-hidden is-focusable is-leaf" style="display: none;">
                        {{ hideNode(node) }}
                      </div>
                    </span>
                  </el-row>
                </el-tree>
              </div>
            </el-col>
            <!-- 按钮列表 -->
            <el-col :span="3">
              <div @click="fabClick"
                   v-permission="['PROJECT_API_SCENARIO:READ+EDIT', 'PROJECT_API_SCENARIO:READ+CREATE']">
                <vue-fab id="fab" mainBtnColor="#783887" size="small" :global-options="globalOptions"
                         :click-auto-close="false" v-outside-click="outsideClick" ref="refFab">
                  <fab-item
                    v-for="(item, index) in buttonData"
                    :key="index"
                    :idx="getIdx(index)"
                    :title="item.title"
                    :title-bg-color="item.titleBgColor"
                    :title-color="item.titleColor"
                    :color="item.titleColor"
                    :icon="item.icon"
                    @clickItem="item.click"/>
                </vue-fab>
              </div>
            </el-col>
          </el-row>
        </div>

        <!--参数设置-->
        <ms-api-variable-advance ref="scenarioVariableAdvance"
                                 :append-to-body="true"
                                 :current-item="currentItem"
                                 :variables="currentScenario.variables"
                                 :scenario-definition="scenarioDefinition"/>

        <!--接口列表-->
        <scenario-api-relevance @save="pushApiOrCase" @close="setHideBtn" ref="scenarioApiRelevance"
                                :is-across-space="true" v-if="type!=='detail'"/>

        <!--自定义接口-->
        <el-drawer v-if="type!=='detail'" :visible.sync="customizeVisible" :destroy-on-close="true" direction="ltr"
                   :withHeader="false" :title="$t('api_test.automation.customize_req')" style="overflow: auto"
                   :modal="false" size="90%">
          <ms-api-customize :request="customizeRequest" @addCustomizeApi="addCustomizeApi"/>
        </el-drawer>
        <!--场景导入 -->
        <scenario-relevance v-if="type!=='detail'" @save="addScenario" @close="setHideBtn" :is-across-space="true"
                            ref="scenarioRelevance"/>

        <!-- 环境 -->
        <api-environment-config v-if="type!=='detail'" ref="environmentConfig" @close="environmentConfigClose"/>

        <!--执行组件-->
        <ms-run :debug="true" v-if="type!=='detail'" :environment="projectEnvMap" :reportId="reportId" :saved="saved"
                :run-data="debugData" :environment-type="environmentType" :environment-group-id="envGroupId"
                :executeType="executeType"
                @runRefresh="runRefresh" @errorRefresh="errorRefresh" ref="runTest"/>
        <!-- 调试结果 -->
        <el-drawer v-if="type!=='detail'" :visible.sync="debugVisible" :destroy-on-close="true" direction="ltr"
                   :withHeader="true" :modal="false" size="80%">
          <ms-api-report-detail :scenario="currentScenario" :report-id="reportId" :debug="true"
                                :currentProjectId="projectId" @refresh="detailRefresh"/>
        </el-drawer>

        <!--场景公共参数-->
        <ms-variable-list v-if="type!=='detail'" @setVariables="setVariables" ref="scenarioParameters"
                          class="ms-sc-variable-header"/>
        <!--外部导入-->
        <api-import v-if="type!=='detail'" ref="apiImport" :saved="false" @refresh="apiImport"/>

        <!--步骤最大化-->
        <ms-drawer :visible="drawer" :size="100" @close="close" direction="default" :show-full-screen="false"
                   :is-show-close="false" style="overflow: hidden" v-if="drawer">
          <maximize-scenario
            :scenario-definition="scenarioDefinition"
            :projectIds.sync="projectIds"
            :projectList="projectList"
            :envMap="projectEnvMap"
            :moduleOptions="moduleOptions"
            :req-error="reqError"
            :req-success="reqSuccess"
            :req-total="reqTotal"
            :req-total-time="reqTotalTime"
            :currentScenario="currentScenario"
            :type="type"
            :debug="debugLoading"
            :reloadDebug="reloadDebug"
            :stepReEnable="stepEnable"
            :message="message"
            :enable-cookie="enableCookieShare"
            :on-sample-error="onSampleError"
            @setEnvType="setEnvType"
            @envGroupId="setEnvGroup"
            @closePage="close"
            @unFullScreen="unFullScreen"
            @showAllBtn="showAllBtn"
            @runDebug="runDebug"
            @handleCommand="handleCommand"
            @setProjectEnvMap="setProjectEnvMap"
            @showScenarioParameters="showScenarioParameters"
            @setCookieShare="setCookieShare"
            @setSampleError="setSampleError"
            @stop="stop"
            @sort="sort"
            @openScenario="openScenario"
            @runScenario="runDebug"
            @stopScenario="stop"
            @editScenarioAdvance="editScenarioAdvance"
            ref="maximizeScenario"/>
        </ms-drawer>
        <ms-change-history ref="changeHistory"/>
        <el-backtop target=".card-content" :visibility-height="100" :right="20"></el-backtop>
      </div>
      <ms-task-center ref="taskCenter" :show-menu="false"/>

      <!--版本对比-->
      <el-dialog
        :fullscreen="true"
        :visible.sync="dialogVisible"
        :destroy-on-close="true"
        @close="closeDiff"
        width="100%">
        <scenario-diff
          v-if="dialogVisible"
          :custom-num="customNum"
          :currentScenarioId="currentScenario.id"
          :dffScenarioId="dffScenarioId"
          :scenarioRefId="scenarioRefId"
          :module-options="moduleOptions"
          :project-env-map="projectEnvMap"
          :old-enable-cookie-share="enableCookieShare"
          :old-on-sample-error="onSampleError"
          :project-list="projectList"
          :new-create-time="newCreateTime"
          :old-create-time="oldCreateTime"
          :old-user-name="oldUserName"
          :type="type"/>
      </el-dialog>

    </ms-main-container>
  </ms-container>
</template>

<script>
import {API_STATUS, PRIORITY} from "../../definition/model/JsonData";
import {buttons, setComponent} from './menu/Menu';
import {parseEnvironment} from "../../definition/model/EnvironmentModel";
import {ELEMENT_TYPE, STEP, TYPE_TO_C} from "./Setting";
import {KeyValue} from "@/business/components/api/definition/model/ApiTestModel";

import {
  getCurrentProjectID,
  getCurrentUser,
  getUUID,
  handleCtrlREvent,
  handleCtrlSEvent,
  hasLicense,
  hasPermission,
  objToStrMap,
  strMapToObj
} from "@/common/js/utils";
import "@/common/css/material-icons.css";
import OutsideClick from "@/common/js/outside-click";
import {
  getReportMessageSocket,
  savePreciseEnvProjectIds,
  saveScenario
} from "@/business/components/api/automation/api-automation";
import MsComponentConfig from "./component/ComponentConfig";
import {ENV_TYPE} from "@/common/js/constants";
import {mergeRequestDocumentData} from "@/business/components/api/definition/api-definition";

const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
const versionHistory = requireComponent.keys().length > 0 ? requireComponent("./version/VersionHistory.vue") : {};

let jsonPath = require('jsonpath');
export default {
  name: "EditApiScenario",
  props: {
    moduleOptions: Array,
    currentScenario: {},
    type: String,
    customNum: {
      type: Boolean,
      default: false
    },
  },
  components: {
    'MsVersionHistory': versionHistory.default,
    MsComponentConfig,
    ScenarioDiff: () => import("@/business/components/api/automation/version/ScenarioDiff"),
    MsVariableList: () => import("./variable/VariableList"),
    ScenarioRelevance: () => import("./api/ScenarioRelevance"),
    ScenarioApiRelevance: () => import("./api/ApiRelevance"),
    ApiEnvironmentConfig: () => import("@/business/components/api/test/components/ApiEnvironmentConfig"),
    MsApiReportDetail: () => import("../report/SysnApiReportDetail"),
    MsInputTag: () => import("./MsInputTag"),
    MsRun: () => import("./DebugRun"),
    MsApiCustomize: () => import("./ApiCustomize"),
    ApiImport: () => import("../../definition/components/import/ApiImport"),
    EnvPopover: () => import("@/business/components/api/automation/scenario/EnvPopover"),
    MaximizeScenario: () => import("./maximize/MaximizeScenario"),
    MsDrawer: () => import("../../../common/components/MsDrawer"),
    MsSelectTree: () => import("../../../common/select-tree/SelectTree"),
    MsChangeHistory: () => import("../../../history/ChangeHistory"),
    MsTaskCenter: () => import("../../../task/TaskCenter"),
    MsApiVariableAdvance: () => import("./../../definition/components/ApiVariableAdvance"),
    MsMainContainer: () => import("@/business/components/common/components/MsMainContainer"),
    MsAsideContainer: () => import("@/business/components/common/components/MsAsideContainer"),
    MsContainer: () => import("@/business/components/common/components/MsContainer"),
    ShowMoreBtn: () => import( "@/business/components/track/case/components/ShowMoreBtn"),
  },
  data() {
    return {
      onSampleError: true,
      showConfigButtonWithOutPermission: false,
      props: {
        label: "label",
        isLeaf: "isLeaf",
        children: "hashTree",
        disabled: false
      },
      moduleObj: {
        id: 'id',
        label: 'name',
      },
      rules: {
        name: [
          {required: true, message: this.$t('test_track.case.input_name'), trigger: 'blur'},
          {max: 100, message: this.$t('test_track.length_less_than') + '100', trigger: 'blur'}
        ],
        userId: [{required: true, message: this.$t('test_track.case.input_maintainer'), trigger: 'change'}],
        apiScenarioModuleId: [{required: true, message: this.$t('test_track.case.input_module'), trigger: 'change'}],
        status: [{required: true, message: this.$t('commons.please_select'), trigger: 'change'}],
        principal: [{required: true, message: this.$t('api_test.definition.request.responsible'), trigger: 'change'}],
        customNum: [
          {required: true, message: "ID必填", trigger: 'blur'},
          {max: 50, message: this.$t('test_track.length_less_than') + '50', trigger: 'blur'}
        ],
      },
      environments: [],
      maintainerOptions: [],
      value: API_STATUS[0].id,
      options: API_STATUS,
      levels: PRIORITY,
      scenario: {},
      loading: false,
      renderComponent: true,
      apiListVisible: false,
      customizeVisible: false,
      isBtnHide: false,
      debugVisible: false,
      customizeRequest: {protocol: "HTTP", type: "API", hashTree: [], referenced: 'Created', active: false},
      operatingElements: [],
      selectedTreeNode: undefined,
      selectedNode: undefined,
      scenarioDefinition: [],
      path: "/api/automation/create",
      debugData: {},
      reportId: "",
      enableCookieShare: false,
      globalOptions: {
        spacing: 30
      },
      response: {},
      projectIds: new Set,
      projectEnvMap: new Map,
      projectList: [],
      drawer: false,
      isFullUrl: true,
      expandedStatus: false,
      stepEnable: true,
      envResult: {
        loading: false
      },
      debug: false,
      saved: false,
      debugLoading: false,
      reqTotal: 0,
      reqSuccess: 0,
      reqError: 0,
      reqTotalTime: 0,
      reloadDebug: "",
      stopDebug: "",
      isTop: false,
      message: "",
      messageWebSocket: {},
      buttonData: [],
      stepFilter: new STEP,
      plugins: [],
      runScenario: undefined,
      showFollow: false,
      envGroupId: "",
      environmentType: ENV_TYPE.JSON,
      executeType: "",
      versionData: [],
      dialogVisible: false,
      currentItem: {},
      pluginDelStep: false,
      isBatchProcess: false,
      isCheckedAll: false,
      selectDataCounts: 0,
      dffScenarioId: "",
      scenarioRefId: "",
      batchOperators: [
        {
          name: this.$t('api_test.automation.bulk_activation_steps'),
          handleClick: this.enableAll,
          permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
        },
        {
          name: this.$t('api_test.automation.batch_disable_steps'),
          handleClick: this.disableAll,
          permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
        },
        {
          name: this.$t('api_test.automation.open_expansion'),
          handleClick: this.openExpansion,
          permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
        },
        {
          name: this.$t('api_test.automation.close_expansion'),
          handleClick: this.closeExpansion,
          permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
        },
        {
          name: this.$t('api_test.definition.request.batch_delete') + "步骤",
          handleClick: this.handleDeleteBatch,
          permissions: ['PROJECT_API_SCENARIO:READ+DELETE']
        },
      ],
      reloadTree: "",
      newCreateTime: 0,
      oldCreateTime: 0,
      oldUserName: '',
      debugReportId: ""
    }
  },
  created() {
    if (!this.currentScenario.apiScenarioModuleId) {
      this.currentScenario.apiScenarioModuleId = "";
    }
    if (this.currentScenario.apiScenarioModuleId === 'default-module') {
      this.currentScenario.apiScenarioModuleId = this.moduleOptions[0].id;
    }
    this.debug = false;
    this.debugLoading = false;
    if (this.stepFilter) {
      this.operatingElements = this.stepFilter.get("ALL");
    }
    this.getWsProjects();
    this.getMaintainerOptions();
    this.getApiScenario();
    this.getEnvironments();
    this.buttonData = buttons(this);
    this.getPlugins().then(() => {
      this.initPlugins();
    });

    if (hasLicense()) {
      this.getVersionHistory();
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.addListener();
    });
  },
  directives: {OutsideClick},
  computed: {
    projectId() {
      return getCurrentProjectID();
    },
    ENV_TYPE() {
      return ENV_TYPE;
    }
  },
  methods: {
    refreshApiScenario() {
      this.getApiScenario(true);
    },
    recursiveSorting(arr) {
      for (let i in arr) {
        arr[i].disabled = true;
        if (arr[i].hashTree != undefined && arr[i].hashTree.length > 0) {
          this.recursiveSorting(arr[i].hashTree);
        }
      }
    },
    chooseHeadsUp() {
      if (this.$refs.stepTree) {
        this.selectDataCounts = this.$refs.stepTree.getCheckedNodes().length;
      }
    },
    checkedAll(v) {
      if (this.$refs.stepTree && this.$refs.stepTree.root && this.$refs.stepTree.root.childNodes) {
        this.recursionChecked(v, this.$refs.stepTree.root.childNodes);
      }
    },
    recursionChecked(v, array) {
      if (array) {
        array.forEach(item => {
          if (item.childNodes && item.childNodes.length > 0) {
            this.recursionChecked(v, item.childNodes);
          }
          item.checked = v;
          if (item.data && item.data.type === 'scenario' && item.data.referenced === 'REF') {
            item.expanded = false;
          }
        })
      }
    },
    batchProcessing() {
      this.isBatchProcess = true;
      this.hideAllTreeNode(this.scenarioDefinition);
      if (this.$refs.stepTree && this.$refs.stepTree.root && this.$refs.stepTree.root.childNodes) {
        this.recursionExpansion([], this.$refs.stepTree.root.childNodes);
      }
      this.reloadTreeStatus();
    },
    cancelBatchProcessing() {
      this.isBatchProcess = false;
      this.isCheckedAll = false;
      if (this.$refs.stepTree && this.$refs.stepTree.root && this.$refs.stepTree.root.childNodes) {
        this.recursionChecked(false, this.$refs.stepTree.root.childNodes);
      }
      this.selectDataCounts = 0;
      this.commandTreeNode();
      this.reloadTreeStatus();
    },
    reloadTreeStatus() {
      this.$nextTick(() => {
        let row = {resourceId: "ms-reload-test"};
        if (this.$refs.stepTree && this.$refs.stepTree.root.data) {
          this.$refs.stepTree.root.data.push(row);
          this.$refs.stepTree.root.data.splice(this.$refs.stepTree.root.data.length - 1, 1);
        }
      });
    },
    openOrClose(node, data) {
      node.expanded = !node.expanded;
      this.pluginOrder(data);
    },
    pluginOrder(nodes) {
      // 兼容历史数据
      if (nodes && nodes.type === 'GenericController' && nodes.hashTree) {
        let data = nodes.hashTree.filter(v => v.type !== "Assertions");
        for (let i = 0; i < data.length; i++) {
          data[i].index = (i + 1);
        }
      }
    },
    hideNode(node) {
      node.isLeaf = true;
      node.visible = false;
    },
    hideAllTreeNode(array) {
      array.forEach(item => {
        item.isLeaf = this.isBatchProcess;
        item.isBatchProcess = this.isBatchProcess;
        item.checkBox = this.isBatchProcess;
        if (item.hashTree && item.hashTree.length > 0) {
          this.hideAllTreeNode(item.hashTree);
        }
      })
    },
    commandTreeNode(node, array) {
      if (!array) {
        array = this.scenarioDefinition;
      }
      let isLeaf = true;
      array.forEach(item => {
        item.checkBox = false;
        if (isLeaf && this.stepFilter.get('ALlSamplerStep').indexOf(item.type) === -1) {
          isLeaf = false;
        }
        if (item.hashTree && item.hashTree.length > 0) {
          this.commandTreeNode(item, item.hashTree);
        } else {
          item.isLeaf = true;
        }
      })
      if (node) {
        node.isBatchProcess = this.isBatchProcess;
        node.checkBox = false;
        node.isLeaf = isLeaf;
      }
    },
    currentUser: () => {
      return getCurrentUser();
    },
    setDomain() {
      if (this.projectEnvMap && this.projectEnvMap.size > 0) {
        let scenario = {
          id: this.currentScenario.id,
          enableCookieShare: this.enableCookieShare,
          name: this.currentScenario.name,
          type: "scenario",
          clazzName: TYPE_TO_C.get("scenario"),
          variables: this.currentScenario.variables,
          headers: this.currentScenario.headers,
          referenced: 'Created',
          environmentMap: strMapToObj(this.projectEnvMap),
          hashTree: this.scenarioDefinition,
          onSampleError: this.onSampleError,
          projectId: this.currentScenario.projectId ? this.currentScenario.projectId : this.projectId,
        };
        let param = {
          definition: JSON.stringify(scenario),
          environmentType: this.environmentType,
          environmentMap: strMapToObj(this.projectEnvMap),
          environmentGroupId: this.envGroupId,
          environmentEnable: false,
        };
        this.$post("/api/automation/setDomain", param, res => {
          if (res.data) {
            let data = JSON.parse(res.data);
            if (data.hashTree) {
              this.sort(data.hashTree);
              let domainMap = new Map();
              this.getEnvDomain(data.hashTree, domainMap);
              this.margeDomain(this.scenarioDefinition, domainMap);
              this.cancelBatchProcessing();
            }
          }
        })
      }
    },
    margeDomain(array, map) {
      array.forEach(item => {
        if (item && map.has(item.resourceId)) {
          item.domain = map.get(item.resourceId);
          item.resourceId = getUUID();
        } else {
          item.domain = "";
        }
        if (item && item.hashTree && item.hashTree.length > 0) {
          this.margeDomain(item.hashTree, map);
        }
      })
    },
    getEnvDomain(array, map) {
      array.forEach(item => {
        if (item && item.resourceId && item.domain) {
          map.set(item.resourceId, item.domain);
        }
        if (item && item.hashTree && item.hashTree.length > 0) {
          this.getEnvDomain(item.hashTree, map);
        }
      })
    },
    initPlugins() {
      if (this.plugins) {
        this.plugins.forEach(item => {
          let plugin = {
            title: item.name,
            show: this.showButton(item.jmeterClazz),
            titleColor: "#555855",
            titleBgColor: "#F4F4FF",
            icon: "colorize",
            click: () => {
              this.addComponent(item.name, item)
            }
          }
          if (this.operatingElements && this.operatingElements.includes(item.jmeterClazz)) {
            this.buttonData.push(plugin);
          }
          this.$nextTick(() => {
            if (!this.currentScenario.name && this.$refs.refFab) {
              this.$refs.refFab.openMenu();
            }
          });
        });
      }
    },
    getPlugins() {
      return new Promise((resolve) => {
        let url = "/plugin/list";
        this.plugins = [];
        this.$get(url, response => {
          let data = response.data;
          if (data) {
            data.forEach(item => {
              if (item.license) {
                if (hasLicense()) {
                  this.plugins.push(item);
                }
              } else {
                this.plugins.push(item);
              }
            })
          }
          resolve();
        });
      });
    },
    stop() {
      if (this.reportId) {
        try {
          if (this.messageWebSocket) {
            this.messageWebSocket.close();
          }
          this.clearNodeStatus(this.$refs.stepTree.root.childNodes);
          this.clearDebug();
          this.$success(this.$t('report.test_stop_success'));
        } catch (e) {
          this.debugLoading = false;
        }
        this.runScenario = undefined;
        // 停止jmeter执行
        let url = "/api/automation/stop/" + this.reportId;
        this.$get(url, response => {
          this.debugLoading = false;
        }, error => {
          this.debugLoading = false;
        });
      }
    },
    clearDebug() {
      this.reqError = 0;
      this.reqTotalTime = 0;
      this.reqTotal = 0;
      this.reqSuccess = 0;
      this.executeType = "";
      this.pluginDelStep = false;
    },
    clearResult(arr) {
      if (arr) {
        arr.forEach(item => {
          item.requestResult = [];
          item.result = undefined;
          item.code = undefined;
          if (item.hashTree && item.hashTree.length > 0) {
            this.clearResult(item.hashTree);
          }
        })
      }
    },
    clearNodeStatus(arr) {
      if (arr) {
        arr.forEach(item => {
          item.code = undefined;
          item.data.code = undefined;
          item.testing = undefined;
          item.data.testing = undefined;
          if (item.childNodes && item.childNodes.length > 0) {
            this.clearNodeStatus(item.childNodes);
          }
        })
      }
    },
    evaluationParent(node, status) {
      if (!node.data.code) {
        node.data.code = "success";
      }
      if (!status) {
        node.data.code = "error";
      }
      node.data.testing = false;
      node.data.debug = true;
      if (node.parent && node.parent.data && node.parent.data.id) {
        this.evaluationParent(node.parent, status);
      }
    },
    resultEvaluationChild(arr, resourceId, status) {
      arr.forEach(item => {
        let id = item.data.id || item.data.resourceId;
        if (id + "_" + item.data.parentIndex === resourceId) {
          item.data.testing = false;
          this.evaluationParent(item.parent, status);
        }
        if (item.childNodes && item.childNodes.length > 0) {
          this.resultEvaluationChild(item.childNodes, resourceId, status);
        }
      })
    },
    resultEvaluation(resourceId, status) {
      if (this.$refs.stepTree && this.$refs.stepTree.root) {
        this.$refs.stepTree.root.childNodes.forEach(item => {
          if (item.data.id + "_" + item.data.parentIndex === resourceId) {
            item.data.testing = false;
          }
          if (item.childNodes && item.childNodes.length > 0) {
            this.resultEvaluationChild(item.childNodes, resourceId, status);
          }
        })
      }
    },
    initMessageSocket() {
      this.debugReportId = getUUID().substring(0, 8);
      this.messageWebSocket = getReportMessageSocket(this.debugReportId);
      this.messageWebSocket.onmessage = this.onDebugMessage;
    },
    runningEditParent(node) {
      if (node.parent && node.parent.data && node.parent.data.id) {
        node.data.testing = true;
        this.runningEditParent(node.parent);
      }
    },
    margeTransaction(item, console, arr) {
      arr.forEach(sub => {
        if (item.data && item.data.id + "_" + item.data.parentIndex === sub.resourceId) {
          sub.responseResult.console = console;
          item.data.requestResult.push(sub);
          // 更新父节点状态
          this.resultEvaluation(sub.resourceId, sub.success);
          item.data.testing = false;
          item.data.debug = true;
        }
        if (sub.subRequestResults && sub.subRequestResults.length > 0) {
          this.margeTransaction(item, console, sub.subRequestResults);
        }
      })
    },
    runningNodeChild(arr, resultData) {
      arr.forEach(item => {
        if (resultData && resultData.startsWith("result_")) {
          let data = JSON.parse(resultData.substring(7));
          if (data.method === 'Request' && data.subRequestResults && data.subRequestResults.length > 0) {
            this.margeTransaction(item, data.responseResult.console, data.subRequestResults);
          } else if ((item.data && item.data.id + "_" + item.data.parentIndex === data.resourceId)
            || (item.data && item.data.resourceId + "_" + item.data.parentIndex === data.resourceId)) {
            if (item.data.requestResult) {
              item.data.requestResult.push(data);
            } else {
              item.data.requestResult = [data];
            }
            // 更新父节点状态
            this.resultEvaluation(data.resourceId, data.success);
            item.data.testing = false;
            item.data.debug = true;
          }
        } else if (item.data && item.data.id + "_" + item.data.parentIndex === resultData) {
          item.data.testing = true;
          this.runningEditParent(item.parent);
        }
        if (item.childNodes && item.childNodes.length > 0) {
          this.runningNodeChild(item.childNodes, resultData);
        }
      })
    },
    runningEvaluation(resultData) {
      if (this.$refs.stepTree && this.$refs.stepTree.root) {
        this.$refs.stepTree.root.childNodes.forEach(item => {
          if (item.data && item.data.id + "_" + item.data.parentIndex === resultData) {
            item.data.testing = true;
          } else if (resultData && resultData.startsWith("result_")) {
            let data = JSON.parse(resultData.substring(7));
            if (data.method === 'Request' && data.subRequestResults && data.subRequestResults.length > 0) {
              this.margeTransaction(item, data.responseResult.console, data.subRequestResults);
            } else if (item.data && item.data.id + "_" + item.data.parentIndex === data.resourceId
              || (item.data && item.data.resourceId + "_" + item.data.parentIndex === data.resourceId)) {
              item.data.requestResult.push(data);
              // 更新父节点状态
              this.resultEvaluation(data.resourceId, data.success);
              item.data.testing = false;
              item.data.debug = true;
            }
          }
          if (item.childNodes && item.childNodes.length > 0) {
            this.runningNodeChild(item.childNodes, resultData);
          }
        })
      }
    },
    onDebugMessage(e) {
      // 确认连接建立成功，开始执行
      if (e && e.data === "CONN_SUCCEEDED") {
        this.run();
      }
      if (e.data && e.data.startsWith("result_")) {
        let data = JSON.parse(e.data.substring(7));
        this.reqTotal += 1;
        let time = data.endTime - data.startTime;
        this.reqTotalTime += time > 0 ? time : 0;
        if (data.error === 0) {
          this.reqSuccess += 1;
        } else {
          this.reqError += 1;
        }
      }
      this.runningEvaluation(e.data);
      this.message = getUUID();
      if (e.data && e.data.indexOf("MS_TEST_END") !== -1) {
        this.runScenario = undefined;
        this.debugLoading = false;
        this.message = "stop";
        this.stopDebug = "stop";
        this.reload();
      }
    },
    handleCommand() {
      this.debug = false;
      this.saved = true;
      this.executeType = "Saved";
      this.mergeScenario(this.scenarioDefinition);
      this.validatePluginData(this.scenarioDefinition);
      if (this.pluginDelStep) {
        this.$error("场景包含插件步骤，对应场景已经删除不能执行！");
        return;
      }
      /*触发执行操作*/
      this.$refs['currentScenario'].validate(async (valid) => {
          if (valid) {
            this.debugLoading = true;
            let definition = JSON.parse(JSON.stringify(this.currentScenario));
            definition.hashTree = this.scenarioDefinition;
            await this.getEnv(JSON.stringify(definition));
            await this.$refs.envPopover.initEnv();
            const sign = await this.$refs.envPopover.checkEnv(this.isFullUrl);
            if (!sign) {
              this.debugLoading = false;
              return;
            }
            this.initParameter();
            this.debugData = {
              id: this.currentScenario.id,
              name: this.currentScenario.name,
              type: "scenario",
              variables: this.currentScenario.variables,
              referenced: 'Created',
              onSampleError: this.onSampleError,
              enableCookieShare: this.enableCookieShare,
              headers: this.currentScenario.headers,
              environmentMap: this.projectEnvMap,
              hashTree: this.scenarioDefinition
            };
            this.reportId = getUUID().substring(0, 8);
            this.debugLoading = false;
            this.pluginDelStep = false;
            this.$emit('refresh');
          }
        }
      )
    },
    validatePluginData(steps) {
      steps.forEach(step => {
        if (step.plugin_del) {
          this.pluginDelStep = true;
        }
        if (step.hashTree && step.hashTree.length > 0) {
          this.validatePluginData(step.hashTree);
        }
      });
    },
    openHis() {
      this.$refs.changeHistory.open(this.currentScenario.id, ["接口自动化", "Api automation", "接口自動化", "API_AUTOMATION"]);
    },
    setModule(id, data) {
      this.currentScenario.apiScenarioModuleId = id;
      this.currentScenario.modulePath = data.path;
    },
    setHideBtn() {
      this.$refs.scenarioRelevance.changeButtonLoadingType();
      this.$refs.scenarioApiRelevance.changeButtonLoadingType();
      this.isBtnHide = false;
    },
    // 打开引用的场景
    openScenario(data) {
      this.$emit('openScenario', data);
    },
    setCookieShare(cookie) {
      this.enableCookieShare = cookie;
    },
    setSampleError(sampleError) {
      this.onSampleError = sampleError;
    },
    showAllBtn() {
      this.$refs.maximizeScenario.showAll();
    },
    addListener() {
      document.addEventListener("keydown", this.createCtrlSHandle);
      document.addEventListener("keydown", this.createCtrlRHandle);
    },
    removeListener() {
      document.removeEventListener("keydown", this.createCtrlSHandle);
      document.removeEventListener("keydown", this.createCtrlRHandle);
    },
    createCtrlSHandle(event) {
      handleCtrlSEvent(event, this.editScenario);
    },
    createCtrlRHandle(event) {
      handleCtrlREvent(event, this.runDebug);
    },
    getIdx(index) {
      return index - 0.33
    },
    setVariables(v, headers) {
      this.currentScenario.variables = v;
      this.currentScenario.headers = headers;
      if (this.path.endsWith("/update")) {
        // 直接更新场景防止编辑内容丢失
        this.editScenario();
      }
      if (this.$refs.maximizeHeader) {
        this.$refs.maximizeHeader.getVariableSize();
      }
      this.reload();
    },
    showButton(...names) {
      for (const name of names) {
        if (name && this.operatingElements && this.operatingElements.includes(name)) {
          return true;
        }
      }
      return false;
    },
    outsideClick(e) {
      e.stopPropagation();
      this.showAll();
      this.buttonData = buttons(this);
      this.initPlugins();
    },
    fabClick() {
      if (this.operatingElements && this.operatingElements.length < 1) {
        if (this.selectedTreeNode && this.selectedTreeNode.referenced === 'REF' || this.selectedTreeNode.disabled) {
          this.$warning(this.$t('api_test.scenario.scenario_warning'));
        } else {
          this.$warning(this.$t('api_test.scenario.scenario_step_warning'));
        }
      }
    },
    addComponent(type, plugin) {
      setComponent(type, this, plugin);
    },
    nodeClick(data, node) {
      if ((data.referenced != 'REF' && data.referenced != 'Deleted' && !data.disabled && this.stepFilter) || data.refType === 'CASE') {
        this.operatingElements = this.stepFilter.get(data.type);
      } else {
        this.operatingElements = [];
      }
      if ((!this.operatingElements && this.stepFilter) || this.stepFilter.get("SpecialSteps").indexOf(data.type) !== -1) {
        this.operatingElements = this.stepFilter.get("ALL");
      }
      this.selectedTreeNode = data;
      this.selectedNode = node;
      this.$store.state.selectStep = data;
      this.buttonData = buttons(this);
      this.initPlugins();
      if (this.buttonData.length === 0 && this.$refs.refFab && this.$refs.refFab.active) {
        this.$refs.refFab.openMenu();
      }
    },
    suggestClick(node) {
      this.response = {};
      if (node.parent && node.parent.data.requestResult) {
        this.response = node.parent.data.requestResult[0];
      }
    },
    showAll() {
      // 控制当有弹出页面操作时禁止刷新按钮列表
      if (!this.customizeVisible && !this.isBtnHide) {
        this.operatingElements = this.stepFilter.get("ALL");
        this.selectedTreeNode = undefined;
        this.$store.state.selectStep = undefined;
      }
    },
    apiListImport() {
      this.isBtnHide = true;
      this.$refs.scenarioApiRelevance.open();
    },
    sort(stepArray) {
      stepArray = stepArray || this.scenarioDefinition;
      this.recursionStep(stepArray);
    },
    recursionStep(stepArray, scenarioProjectId, fullPath, isGeneric) {
      for (let i in stepArray) {
        let step = stepArray[i];
        step.index = !isGeneric ? Number(i) + 1 : step.index;
        if (step.type === 'GenericController') {
          this.pluginOrder(step);
        }
        step.resourceId = step.resourceId || getUUID();
        // 历史数据处理
        if (step.type === "HTTPSamplerProxy" && !step.headers) {
          step.headers = [new KeyValue()];
        }
        if (step.type === ELEMENT_TYPE.LoopController
          && step.loopType === "LOOP_COUNT"
          && step.hashTree
          && step.hashTree.length > 1) {
          step.countController.proceed = true;
        }
        step.clazzName = step.clazzName || TYPE_TO_C.get(step.type);
        if (step && step.authManager && !step.authManager.clazzName) {
          step.authManager.clazzName = TYPE_TO_C.get(step.authManager.type);
        }
        // 如果自身没有ID并且场景有ID则赋值场景ID，否则赋值当前项目ID
        step.projectId = step.projectId || scenarioProjectId || this.projectId;
        // 添加debug结果
        step.parentIndex = fullPath ? fullPath + "_" + step.index : step.index;
        if (step.hashTree && step.hashTree.length > 0) {
          this.recursionStep(step.hashTree, step.projectId, step.parentIndex, step.type === 'GenericController');
        }
      }
    },
    addCustomizeApi(request) {
      this.customizeVisible = false;
      request.enable === undefined ? request.enable = true : request.enable;
      if (this.selectedTreeNode !== undefined) {
        if (this.stepFilter.get("SpecialSteps").indexOf(this.selectedTreeNode.type) !== -1) {
          this.scenarioDefinition.splice(this.selectedTreeNode.index, 0, request);
          this.$store.state.forceRerenderIndex = getUUID();
        } else {
          this.selectedTreeNode.hashTree.push(request);
        }
      } else {
        this.scenarioDefinition.push(request);
      }
      this.customizeRequest = {};
      this.sort();
      this.reload();
    },
    addScenario(arr) {
      if (arr && arr.length > 0) {
        arr.forEach(item => {
          if (item.id === this.currentScenario.id) {
            this.$error(this.$t("api_test.scenario.scenario_error"));
            this.$refs.scenarioRelevance.changeButtonLoadingType();
            return;
          }
          if (!item.hashTree) {
            item.hashTree = [];
          }
          this.resetResourceId(item.hashTree);
          item.enable === undefined ? item.enable = true : item.enable;
          item.variableEnable = item.variableEnable === undefined ? true : item.variableEnable;
          if (this.selectedTreeNode !== undefined) {
            if (this.stepFilter.get("SpecialSteps").indexOf(this.selectedTreeNode.type) !== -1) {
              this.scenarioDefinition.splice(this.selectedTreeNode.index, 0, item);
              this.$store.state.forceRerenderIndex = getUUID();
            } else {
              this.selectedTreeNode.hashTree.push(item);
            }
          } else {
            this.scenarioDefinition.push(item);
          }
        })
      }
      this.isBtnHide = false;
      // 历史数据兼容处理
      if (this.selectedTreeNode && this.selectedTreeNode.type === 'GenericController') {
        this.pluginOrder(this.selectedTreeNode);
      } else {
        this.sort();
      }
      this.cancelBatchProcessing();
    },
    setApiParameter(item, refType, referenced) {
      let request = {};
      if (Object.prototype.toString.call(item.request).indexOf("String") > 0) {
        request = JSON.parse(item.request);
      } else {
        request = item.request;
      }
      if (item.protocol) {
        request.protocol = item.protocol;
      }
      if (request.protocol === "DUBBO") {
        request.protocol = "dubbo://";
      }
      request.id = item.id;
      request.name = item.name;
      request.refType = refType;
      request.referenced = referenced;
      request.enable === undefined ? request.enable = true : request.enable;
      request.active = false;
      request.resourceId = getUUID();
      request.projectId = item.projectId;
      request.num = item.num;
      request.versionEnable = item.versionEnable;
      request.versionId = item.versionId;
      request.versionName = item.versionName;
      request.domain = "";
      request.requestResult = [];
      if (!request.url) {
        request.url = "";
      }
      if (!request.hashTree) {
        request.hashTree = [];
      }
      if (referenced === 'REF' && request.hashTree) {
        this.recursiveSorting(request.hashTree);
      }
      if (this.selectedTreeNode !== undefined) {
        if (this.stepFilter.get("SpecialSteps").indexOf(this.selectedTreeNode.type) !== -1) {
          this.scenarioDefinition.splice(this.selectedTreeNode.index, 0, request);
          this.$store.state.forceRerenderIndex = getUUID();
        } else {
          this.selectedTreeNode.hashTree.push(request);
        }
      } else {
        this.scenarioDefinition.push(request);
      }
    },
    pushApiOrCase(data, refType, referenced) {
      data.forEach(item => {
        this.setApiParameter(item, refType, referenced);
      });
      this.isBtnHide = false;
      this.$refs.scenarioApiRelevance.changeButtonLoadingType();
      // 历史数据兼容处理
      if (this.selectedTreeNode && this.selectedTreeNode.type === 'GenericController') {
        this.pluginOrder(this.selectedTreeNode);
      } else {
        this.sort();
      }
      this.cancelBatchProcessing();
    },
    getMaintainerOptions() {
      this.$get('/user/project/member/list', response => {
        this.maintainerOptions = response.data;
      });
    },
    openTagConfig() {
      if (!this.projectId) {
        this.$error(this.$t('api_test.select_project'));
        return;
      }
      this.$refs.tag.open();
    },
    remove(row, node) {
      let name = row === undefined || row.name === undefined ? "" : row.name;
      this.$alert(this.$t('api_test.definition.request.delete_confirm_step') + ' ' + name + " ？", '', {
        confirmButtonText: this.$t('commons.confirm'),
        callback: (action) => {
          if (action === 'confirm') {
            let parent = node.parent
            let hashTree = parent.data.hashTree || parent.data;
            let index = hashTree.findIndex(d => d.resourceId !== undefined && row.resourceId !== undefined && d.resourceId === row.resourceId)
            hashTree.splice(index, 1);
            //删除空步骤
            while (
              parent &&
              parent.data &&
              parent.data.hashTree &&
              parent.data.hashTree.length <= 0 &&
              parent.data.type === "scenario"
              ) {
              parent = parent.parent;
              if (!parent) {
                break;
              }
              hashTree = parent.data.hashTree || parent.data;
              index = hashTree.findIndex(
                (d) =>
                  d.id != undefined && row.id != undefined && d.id === row.id
              );
              hashTree.splice(index, 1);
            }
            this.sort();
            this.forceRerender();
          }
        }
      });
    },
    resetResourceId(hashTree) {
      hashTree.forEach(item => {
        item.resourceId = item.resourceId || getUUID();
        if (item.hashTree && item.hashTree.length > 0) {
          this.resetResourceId(item.hashTree);
        }
      })
    },
    copyRow(row, node) {
      const parent = node.parent
      const hashTree = parent.data.hashTree || parent.data;
      // 深度复制
      let obj = JSON.parse(JSON.stringify(row));
      obj.resourceId = getUUID();
      if (obj.hashTree && obj.hashTree.length > 0) {
        this.resetResourceId(obj.hashTree);
      }
      if (obj.name) {
        obj.name = obj.name + '_copy';
      }
      const index = hashTree.findIndex(d => d.resourceId === row.resourceId);
      if (index !== -1) {
        hashTree.splice(index + 1, 0, obj);
      } else {
        hashTree.push(obj);
      }
      this.sort();
    },
    reload() {
      this.loading = true
      this.$nextTick(() => {
        this.loading = false
      });
    },
    forceRerender() {
      this.$nextTick(() => {
        this.$store.state.forceRerenderIndex = getUUID();
      });
    },
    run() {
      this.reportId = this.debugReportId;
    },
    mergeScenario(data) {
      data.forEach(item => {
        mergeRequestDocumentData(item);
        if (item.hashTree && item.hashTree.length > 0) {
          this.mergeScenario(item.hashTree);
        }
      })
    },
    runDebug(runScenario) {
      if (!hasPermission('PROJECT_API_SCENARIO:READ+EDIT')) {
        return;
      }
      this.mergeScenario(this.scenarioDefinition);
      if (this.debugLoading) {
        return;
      }
      this.debugLoading = true;
      if (this.scenarioDefinition.length < 1) {
        this.debugLoading = false;
        return;
      }
      let enableArray;
      for (let i = 0; i < this.scenarioDefinition.length; i++) {
        if (this.scenarioDefinition[i].enable) {
          enableArray = this.scenarioDefinition[i];
          break;
        }
      }
      if (!enableArray) {
        this.$warning(this.$t('api_test.definition.request.debug_warning'));
        this.debugLoading = false;
        return;
      }

      this.stopDebug = "";
      this.clearDebug();
      this.validatePluginData(this.scenarioDefinition);
      if (this.pluginDelStep) {
        this.debugLoading = false;
        this.$error("场景包含插件步骤，对应场景已经删除不能调试！");
        return;
      }
      this.clearResult(this.scenarioDefinition);
      this.clearNodeStatus(this.$refs.stepTree.root.childNodes);
      this.saved = runScenario && runScenario.stepScenario ? false : true;
      /*触发执行操作*/
      this.$refs.currentScenario.validate(async (valid) => {
        if (valid) {
          let definition = JSON.parse(JSON.stringify(this.currentScenario));
          definition.hashTree = this.scenarioDefinition;
          await this.getEnv(JSON.stringify(definition));
          await this.$refs.envPopover.initEnv();
          const sign = await this.$refs.envPopover.checkEnv(this.isFullUrl);
          if (!sign) {
            this.debugLoading = false;
            return;
          }
          let scenario = undefined;
          if (runScenario && runScenario.type === 'scenario') {
            scenario = runScenario;
            this.runScenario = runScenario;
          }
          //调试时不再保存
          this.debugData = {
            id: scenario ? scenario.id : this.currentScenario.id,
            name: scenario ? scenario.name : this.currentScenario.name,
            type: "scenario",
            variables: scenario ? scenario.variables : this.currentScenario.variables,
            referenced: 'Created',
            enableCookieShare: this.enableCookieShare,
            headers: scenario ? scenario.headers : this.currentScenario.headers,
            environmentMap: scenario && scenario.environmentEnable ? scenario.environmentMap : this.projectEnvMap,
            hashTree: scenario ? scenario.hashTree : this.scenarioDefinition,
            onSampleError: this.onSampleError,
          };
          if (scenario && scenario.environmentEnable) {
            this.debugData.environmentEnable = scenario.environmentEnable;
            this.debugLoading = false;
          } else {
            this.debugLoading = true;
          }
          this.debug = true;
          this.pluginDelStep = false;
          // 建立消息链接
          this.initMessageSocket();
        } else {
          this.debugLoading = false;
        }
      })
    },
    getEnvironments() {
      if (this.projectId) {
        this.$get('/api/environment/list/' + this.projectId, response => {
          this.environments = response.data;
          this.environments.forEach(environment => {
            parseEnvironment(environment);
          });
          //检查场景是否需要先进行保存
          this.checkDataIsCopy();
        });
      }
    },
    checkDataIsCopy() {
      //  如果是复制按钮创建的场景，直接进行保存
      if (this.currentScenario.copy) {
        this.editScenario(false);
      }
    },

    openEnvironmentConfig() {
      if (!this.projectId) {
        this.$error(this.$t('api_test.select_project'));
        return;
      }
      this.$refs.environmentConfig.open(this.projectId);
    },
    environmentConfigClose() {
      this.getEnvironments();
    },
    allowDrop(draggingNode, dropNode, dropType) {
      if (draggingNode.data.type === 'Assertions' || dropNode.data.type === 'Assertions') {
        return false;
      }
      // 增加插件权限控制
      if (dropType != "inner") {
        if (draggingNode.data.disabled && draggingNode.parent && draggingNode.parent.data && draggingNode.parent.data.disabled) {
          return false;
        }
        if (draggingNode && dropNode && draggingNode.level >= dropNode.level) {
          return true;
        }
        return false;
      } else if (dropType === "inner" && dropNode.data.referenced !== 'REF' && dropNode.data.referenced !== 'Deleted'
        && (this.stepFilter.get(dropNode.data.type) && this.stepFilter.get(dropNode.data.type).indexOf(draggingNode.data.type) != -1)) {
        return true;
      }
      return false;
    },
    allowDrag(draggingNode, dropNode, dropType) {
      if (dropNode && draggingNode && dropType) {
        this.sort();
        this.forceRerender();
        this.cancelBatchProcessing();
      }
    },
    editScenario() {
      this.mergeScenario(this.scenarioDefinition);
      if (!document.getElementById("inputDelay")) {
        return;
      }
      this.validatePluginData(this.scenarioDefinition);
      if (this.pluginDelStep) {
        this.$error("场景包含插件步骤，对应场景已经删除不能编辑！");
        return;
      }
      return new Promise((resolve) => {
        document.getElementById("inputDelay").focus();  //  保存前在input框自动失焦，以免保存失败
        if (this.$refs['currentScenario']) {
          this.$refs['currentScenario'].validate(async (valid) => {
            if (valid) {
              await this.setParameter();
              if (!this.currentScenario.versionId) {
                if (this.$refs.versionHistory && this.$refs.versionHistory.currentVersion) {
                  this.currentScenario.versionId = this.$refs.versionHistory.currentVersion.id;
                }
              }
              saveScenario(this.path, this.currentScenario, this.scenarioDefinition, this, (response) => {
                this.$success(this.$t('commons.save_success'));
                this.path = "/api/automation/update";
                this.$store.state.pluginFiles = [];
                if (response.data) {
                  this.currentScenario.id = response.data.id;
                  if (!this.currentScenario.refId && response.data.refId) {
                    this.currentScenario.refId = response.data.refId;
                  }
                }
                // 保存成功后刷新历史版本
                this.getVersionHistory();
                if (this.currentScenario.tags instanceof String) {
                  this.currentScenario.tags = JSON.parse(this.currentScenario.tags);
                }
                if (this.currentScenario.copy) {
                  this.currentScenario.copy = null;
                }
                if (this.currentScenario.type) {
                  this.currentScenario.type = null;
                }
                this.pluginDelStep = false;
                // 记录改变后的数据数据
                let v1 = {
                  apiScenarioModuleId: this.currentScenario.apiScenarioModuleId,
                  name: this.currentScenario.name,
                  status: this.currentScenario.status,
                  principal: this.currentScenario.principal,
                  level: this.currentScenario.level,
                  tags: this.currentScenario.tags,
                  description: this.currentScenario.description,
                  scenarioDefinition: JSON.parse(JSON.stringify(this.scenarioDefinition))
                };
                this.currentScenario.scenarioDefinitionOrg = v1;
                this.currentScenario.scenarioDefinition = this.scenarioDefinition;
                this.$emit('refresh', this.currentScenario);
                resolve();
              });
            } else {
              if (this.$refs.versionHistory) {
                this.$refs.versionHistory.loading = false;
              }
            }
          })
        }
      });
    },
    getEnv(definition) {
      return new Promise((resolve) => {
        this.$post("/api/automation/getApiScenarioEnv", {definition: definition}, res => {
          if (res.data) {
            this.projectIds = new Set(res.data.projectIds);
            this.projectIds.add(this.projectId);
            this.isFullUrl = res.data.fullUrl;
          }
          resolve();
        })
      });
    },
    getApiScenario(isRefresh) {
      this.loading = true;
      this.isBatchProcess = false;
      this.stepEnable = true;
      this.isCheckedAll = false;
      this.selectDataCounts = 0;
      if (this.currentScenario.tags !== undefined && this.currentScenario.tags) {
        if (!(this.currentScenario.tags instanceof Array)) {
          this.currentScenario.tags = JSON.parse(this.currentScenario.tags);
        }
      } else {
        this.$set(this.currentScenario, 'tags', [])
      }
      if (!this.currentScenario.variables) {
        this.currentScenario.variables = [];
      }
      if (!this.currentScenario.headers) {
        this.currentScenario.headers = [];
      }
      if (this.currentScenario && this.currentScenario.id) {
        this.result = this.$get("/api/automation/getApiScenario/" + this.currentScenario.id, response => {
          if (response.data) {
            this.currentScenario.apiScenarioModuleId = response.data.apiScenarioModuleId;
            this.currentScenario.modulePath = response.data.modulePath;
            this.path = "/api/automation/update";
            if (response.data.scenarioDefinition != null) {
              let obj = JSON.parse(response.data.scenarioDefinition);
              if (obj) {
                if (response.data.environmentJson) {
                  this.projectEnvMap = objToStrMap(JSON.parse(response.data.environmentJson));
                } else {
                  // 兼容历史数据
                  this.projectEnvMap.set(this.projectId, obj.environmentId);
                }
                if (!this.$store.state.scenarioEnvMap || !(this.$store.state.scenarioEnvMap instanceof Map)) {
                  this.$store.state.scenarioEnvMap = new Map();
                }
                this.projectEnvMap.forEach((v, k) => {
                  this.$store.state.scenarioEnvMap.set(this.currentScenario.id + "_" + k, v);
                })
                this.envGroupId = response.data.environmentGroupId;
                if (response.data.environmentType) {
                  this.environmentType = response.data.environmentType;
                }
                this.currentScenario.variables = [];
                if (obj.headers) {
                  this.currentScenario.headers = obj.headers;
                }
                let index = 1;
                if (obj.variables) {
                  obj.variables.forEach(item => {
                    // 兼容历史数据
                    if (item.name) {
                      if (!item.type) {
                        item.type = "CONSTANT";
                        item.id = getUUID();
                      }
                      item.num = index;
                      this.currentScenario.variables.push(item);
                      index++;
                    }
                  })
                }
                this.enableCookieShare = obj.enableCookieShare;
                if (obj.onSampleError === undefined) {
                  this.onSampleError = true;
                } else {
                  this.onSampleError = obj.onSampleError;
                }
                this.dataProcessing(obj.hashTree);
                this.scenarioDefinition = obj.hashTree;
              }
            }
            if (this.currentScenario.copy) {
              this.path = "/api/automation/create";
            }
            this.$get('/api/automation/follow/' + this.currentScenario.id, response => {
              this.currentScenario.follows = response.data;
              for (let i = 0; i < response.data.length; i++) {
                if (response.data[i] === this.currentUser().id) {
                  this.showFollow = true;
                  break;
                }
              }
            });
          }
          this.loading = false;
          this.sort();
          this.$nextTick(() => {
            this.cancelBatchProcessing();
          });
          if (isRefresh) {
            this.reloadTree = getUUID();
          }
          // 记录初始化数据
          let v1 = {
            apiScenarioModuleId: this.currentScenario.apiScenarioModuleId,
            name: this.currentScenario.name,
            status: this.currentScenario.status,
            principal: this.currentScenario.principal,
            level: this.currentScenario.level,
            tags: this.currentScenario.tags,
            description: this.currentScenario.description,
            scenarioDefinition: JSON.parse(JSON.stringify(this.scenarioDefinition))
          };

          this.currentScenario.scenarioDefinitionOrg = v1;
          this.currentScenario.scenarioDefinition = this.scenarioDefinition;
        })
      }
    },
    dataProcessing(stepArray) {
      if (stepArray) {
        for (let i in stepArray) {
          let typeArray = ["JDBCPostProcessor", "JDBCSampler", "JDBCPreProcessor"]
          if (typeArray.indexOf(stepArray[i].type) !== -1) {
            stepArray[i].originalDataSourceId = stepArray[i].dataSourceId;
            stepArray[i].originalEnvironmentId = stepArray[i].environmentId;
          }
          if (!stepArray[i].hashTree) {
            stepArray[i].hashTree = [];
          }
          if (stepArray[i].type === "Assertions" && !stepArray[i].document) {
            stepArray[i].document = {
              type: "JSON",
              data: {xmlFollowAPI: false, jsonFollowAPI: false, json: [], xml: []}
            };
          }
          if (stepArray[i].hashTree.length > 0) {
            this.dataProcessing(stepArray[i].hashTree);
          }
        }
      }
    },

    formatData(hashTree) {
      for (let i in hashTree) {
        if (hashTree[i] && TYPE_TO_C.get(hashTree[i].type) && !hashTree[i].clazzName) {
          hashTree[i].clazzName = TYPE_TO_C.get(hashTree[i].type);
        }
        if (hashTree[i] && hashTree[i].authManager && !hashTree[i].authManager.clazzName) {
          hashTree[i].authManager.clazzName = TYPE_TO_C.get(hashTree[i].authManager.type);
        }
        if (hashTree[i].hashTree && hashTree[i].hashTree.length > 0) {
          this.formatData(hashTree[i].hashTree);
        }
      }
    },
    initParameter() {
      this.currentScenario.stepTotal = this.scenarioDefinition.length;
      if (!this.currentScenario.projectId) {
        this.currentScenario.projectId = this.projectId;
      }
      // 构建一个场景对象 方便引用处理
      let scenario = {
        id: this.currentScenario.id,
        enableCookieShare: this.enableCookieShare,
        name: this.currentScenario.name,
        type: "scenario",
        clazzName: TYPE_TO_C.get("scenario"),
        variables: this.currentScenario.variables,
        headers: this.currentScenario.headers,
        referenced: 'Created',
        environmentMap: strMapToObj(this.projectEnvMap),
        hashTree: this.scenarioDefinition,
        onSampleError: this.onSampleError,
        projectId: this.currentScenario.projectId ? this.currentScenario.projectId : this.projectId,
      };
      // 历史数据处理
      if (scenario.hashTree) {
        this.formatData(scenario.hashTree);
      }
      this.currentScenario.environmentType = this.environmentType;
      this.currentScenario.environmentJson = JSON.stringify(strMapToObj(this.projectEnvMap));
      this.currentScenario.environmentGroupId = this.envGroupId;
      this.currentScenario.scenarioDefinition = scenario;
      if (this.currentScenario.tags instanceof Array) {
        this.currentScenario.tags = JSON.stringify(this.currentScenario.tags);
      }
      if (this.currentModule != null) {
        this.currentScenario.modulePath = this.currentModule.method !== undefined ? this.currentModule.method : null;
        this.currentScenario.apiScenarioModuleId = this.currentModule.id;
      }
    },
    async setParameter() {
      this.initParameter();
      // 保存时同步所需要的项目环境
      savePreciseEnvProjectIds(this.projectIds, this.projectEnvMap);
    },
    runRefresh() {
      if (!this.debug) {
        this.debugVisible = true;
        this.loading = false;
      }
    },
    errorRefresh(error) {
      this.debug = false;
      this.isTop = false;
      this.debugLoading = false;
      this.debugVisible = false;
      this.loading = false;
      this.runScenario = undefined;
      this.message = "stop";
      this.debugData = {};
    },
    showScenarioParameters() {
      this.$refs.scenarioParameters.open(this.currentScenario.variables, this.currentScenario.headers);
    },
    apiImport(importData) {
      if (importData && importData.data) {
        importData.data.forEach(item => {
          this.setApiParameter(item, "API", "OT_IMPORT");
        })
        this.sort();
        this.reload();
      }
    },
    getVariableSize() {
      let size = 0;
      if (this.currentScenario.variables) {
        size += this.currentScenario.variables.length;
      }
      if (this.currentScenario.headers && this.currentScenario.headers.length > 1) {
        size += this.currentScenario.headers.length - 1;
      }
      return size;
    },
    handleEnv() {
      this.$refs.apiScenarioEnv.open();
    },
    setProjectEnvMap(projectEnvMap) {
      this.projectEnvMap = projectEnvMap;
      if (!this.$store.state.scenarioEnvMap) {
        this.$store.state.scenarioEnvMap = new Map();
      }
      let map = objToStrMap(JSON.parse(JSON.stringify(this.$store.state.scenarioEnvMap)));
      this.projectEnvMap.forEach((v, k) => {
        let key = this.currentScenario.id + "_" + k;
        map.set(key, v);
      });
      this.$store.state.scenarioEnvMap = map;
      this.setDomain(true);
      this.setStep(this.scenarioDefinition);
    },
    setStep(stepArray) {
      for (let i in stepArray) {
        let typeArray = ["JDBCPostProcessor", "JDBCSampler", "JDBCPreProcessor"]
        if (typeArray.indexOf(stepArray[i].type) !== -1) {
          if (stepArray[i].customizeReq) {
            if (stepArray[i].isRefEnvironment) {
              this.setStepEnv(stepArray[i]);
            }
          } else {
            this.setStepEnv(stepArray[i]);
          }
        }
        if (stepArray[i].hashTree && stepArray[i].hashTree.length > 0) {
          this.setStep(stepArray[i].hashTree);
        }
      }
    },

    setStepEnv(request) {
      let envId = "";
      let projectId = request.projectId ? request.projectId : this.projectId;
      if (this.projectEnvMap.has(projectId)) {
        envId = this.projectEnvMap.get(projectId);
      }
      // 场景开启自身环境
      if (request.environmentEnable && request.refEevMap) {
        let obj = Object.prototype.toString.call(request.refEevMap).match(/\[object (\w+)\]/)[1].toLowerCase();
        if (obj !== 'object' && obj !== "map") {
          request.refEevMap = objToStrMap(JSON.parse(request.refEevMap));
        } else if (obj === 'object' && obj !== "map") {
          request.refEevMap = objToStrMap(request.refEevMap);
        }
        if (request.refEevMap instanceof Map && request.refEevMap.has(projectId)) {
          envId = request.refEevMap.get(projectId);
        }
      }
      if (envId === request.originalEnvironmentId && request.originalDataSourceId) {
        request.dataSourceId = request.originalDataSourceId;
      }
      let targetDataSourceName = "";
      let currentEnvironment = {};
      this.environments.forEach(environment => {
        // 找到原始环境和数据源名称
        if (environment.id === request.environmentId && environment.id !== envId) {
          if (environment.config && environment.config.databaseConfigs) {
            environment.config.databaseConfigs.forEach(item => {
              if (item.id === request.dataSourceId) {
                targetDataSourceName = item.name;
              }
            });
          }
        }
        if (envId && environment.id === envId) {
          currentEnvironment = environment;
        }
      });
      this.initDataSource(envId, currentEnvironment, targetDataSourceName, request);
    },
    initDataSource(envId, currentEnvironment, targetDataSourceName, request) {
      this.databaseConfigsOptions = [];
      if (envId) {
        request.environmentId = envId;
      } else {
        for (let i in this.environments) {
          if (this.environments[i].id === request.environmentId) {
            currentEnvironment = this.environments[i];
            break;
          }
        }
      }
      let flag = false;
      if (currentEnvironment && currentEnvironment.config && currentEnvironment.config.databaseConfigs) {
        currentEnvironment.config.databaseConfigs.forEach(item => {
          if (item.id === request.dataSourceId) {
            flag = true;
          }
          // 按照名称匹配
          else if (targetDataSourceName && item.name === targetDataSourceName) {
            request.dataSourceId = item.id;
            flag = true;
          }
          this.databaseConfigsOptions.push(item);
        });
        if (!flag && currentEnvironment.config.databaseConfigs.length > 0) {
          request.dataSourceId = currentEnvironment.config.databaseConfigs[0].id;
          flag = true;
        }
      }
      if (!flag) {
        request.dataSourceId = "";
      }
    },
    setEnvGroup(id) {
      this.envGroupId = id;
      this.setDomain(true);
    },
    setEnvType(val) {
      this.environmentType = val;
    },
    getWsProjects() {
      this.$get("/project/getOwnerProjects", res => {
        this.projectList = res.data;
      })
    },
    refReload() {
      this.reload();
    },
    detailRefresh(result) {
      // 把执行结果分发给各个请求
      this.debugData = {};
    },
    fullScreen() {
      this.drawer = true;
    },
    unFullScreen() {
      this.drawer = false;
      this.reloadTree = getUUID();
    },
    close(name) {
      this.drawer = false;
      this.$emit('closePage', name);
    },
    showPopover() {
      let definition = JSON.parse(JSON.stringify(this.currentScenario));
      definition.hashTree = this.scenarioDefinition;
      this.envResult.loading = true;
      this.getEnv(JSON.stringify(definition)).then(() => {
        this.$refs.envPopover.openEnvSelect();
        this.envResult.loading = false;
      })
    },
    changeNodeStatus(resourceIds, nodes) {
      for (let i in nodes) {
        if (nodes[i] && !(nodes[i].type === 'scenario' && nodes[i].referenced === 'REF')) {
          if (resourceIds.indexOf(nodes[i].resourceId) !== -1) {
            nodes[i].active = this.expandedStatus;
          }
          if (nodes[i].hashTree && nodes[i].hashTree.length > 0 && !this.expandedStatus) {
            this.changeNodeStatus(resourceIds, nodes[i].hashTree);
          }
        }
      }
    },
    getAllResourceIds() {
      if (this.$refs.stepTree) {
        return this.$refs.stepTree.getCheckedKeys();
      }
      return [];
    },
    checkALevelChecked() {
      let resourceIds = [];
      if (this.$refs.stepTree) {
        this.$refs.stepTree.root.childNodes.forEach(item => {
          if (item.checked) {
            resourceIds.push(item.data.resourceId);
          }
        })
      }
      return resourceIds;
    },
    recursionExpansion(resourceIds, array) {
      if (array) {
        array.forEach(item => {
          if (item.data && item.data.type === 'scenario' && item.data.referenced === 'REF') {
            item.expanded = false;
          } else {
            if (resourceIds.indexOf(item.data.resourceId) !== -1) {
              item.expanded = this.expandedStatus;
            }
          }
          if (item.childNodes && item.childNodes.length > 0) {
            this.recursionExpansion(resourceIds, item.childNodes);
          }
        })
      }
    },
    openExpansion() {
      this.expandedStatus = true;
      let resourceIds = [];
      let openResourceIds = this.checkALevelChecked();
      if (openResourceIds.length > 20) {
        resourceIds = openResourceIds.slice(0, 20);
      } else {
        resourceIds = this.getAllResourceIds();
      }
      this.changeNodeStatus(resourceIds, this.scenarioDefinition);
      this.recursionExpansion(resourceIds, this.$refs.stepTree.root.childNodes);
    },
    closeExpansion() {
      this.expandedStatus = false;
      let resourceIds = this.getAllResourceIds();
      this.changeNodeStatus(resourceIds, this.scenarioDefinition);
      this.recursionExpansion(resourceIds, this.$refs.stepTree.root.childNodes);
    },
    stepStatus(resourceIds, nodes) {
      for (let i in nodes) {
        if (nodes[i]) {
          if (resourceIds.indexOf(nodes[i].resourceId) !== -1) {
            nodes[i].enable = this.stepEnable;
          }
          if (nodes[i].hashTree != undefined && nodes[i].hashTree.length > 0) {
            this.stepStatus(resourceIds, nodes[i].hashTree);
          }
        }
      }
    },
    enableAll() {
      this.stepEnable = true;
      let resourceIds = this.getAllResourceIds();
      this.stepStatus(resourceIds, this.scenarioDefinition);
    },
    disableAll() {
      this.stepEnable = false;
      let resourceIds = this.getAllResourceIds();
      this.stepStatus(resourceIds, this.scenarioDefinition);
    },
    handleDeleteBatch() {
      this.$alert(this.$t('test_track.module.delete_batch_confirm'), '', {
        confirmButtonText: this.$t('commons.confirm'),
        callback: (action) => {
          if (action === 'confirm') {
            this.getAllResourceIds().forEach(item => {
              this.recursionDelete(item, this.scenarioDefinition);
            });
            this.sort();
            if (this.scenarioDefinition.length <= 1) {
              this.cancelBatchProcessing();
            } else {
              this.forceRerender();
            }
          }
        }
      });
    },
    recursionDelete(resourceId, nodes) {
      for (let i in nodes) {
        if (nodes[i]) {
          if (resourceId === nodes[i].resourceId) {
            nodes.splice(i, 1);
          } else {
            if (nodes[i].hashTree != undefined && nodes[i].hashTree.length > 0) {
              this.recursionDelete(resourceId, nodes[i].hashTree);
            }
          }
        }
      }
    },
    showHistory() {
      this.$refs.taskCenter.openScenarioHistory(this.currentScenario.id);
    },
    saveFollow() {
      if (this.showFollow) {
        this.showFollow = false;
        for (let i = 0; i < this.currentScenario.follows.length; i++) {
          if (this.currentScenario.follows[i] === this.currentUser().id) {
            this.currentScenario.follows.splice(i, 1)
            break;
          }
        }
        if (this.currentScenario.id) {
          this.$post("/api/automation/update/follows/" + this.currentScenario.id, this.currentScenario.follows, () => {
            this.$success(this.$t('commons.cancel_follow_success'));
          });
        }
      } else {
        this.showFollow = true;
        if (!this.currentScenario.follows) {
          this.currentScenario.follows = [];
        }
        this.currentScenario.follows.push(this.currentUser().id)
        if (this.currentScenario.id) {
          this.$post("/api/automation/update/follows/" + this.currentScenario.id, this.currentScenario.follows, () => {
            this.$success(this.$t('commons.follow_success'));
          });
        }
      }
    },
    editScenarioAdvance(data) {
      // 打开编辑参数设置对话框，并且传递修改的蓝笔引用值参数
      this.currentItem = data;
      this.$refs.scenarioVariableAdvance.open();
    },
    getVersionHistory() {
      this.$get('/api/automation/versions/' + this.currentScenario.id, response => {
        if (this.currentScenario.copy) {
          this.versionData = response.data.filter(v => v.versionId === this.currentScenario.versionId);
        } else {
          this.versionData = response.data;
        }
      });
    },
    compare(row) {
      this.scenarioRefId = this.currentScenario.refId;
      this.dffScenarioId = row.id;
      this.newCreateTime = row.createTime
      this.oldUserName = this.currentScenario.userName
      this.oldCreateTime = this.$refs.versionHistory.versionOptions.filter(v => v.id === this.currentScenario.versionId)[0].createTime;
      this.dialogVisible = true;
    },
    closeDiff() {
      this.oldScenarioDefinition = []
    },

    checkout(row) {
      let api = this.versionData.filter(v => v.versionId === row.id)[0];
      if (api.tags && api.tags.length > 0) {
        api.tags = JSON.parse(api.tags);
      }
      Object.assign(this.currentScenario, api);
      this.getApiScenario();
      this.getVersionHistory();
    },
    create(row) {
      // 创建新版本
      this.currentScenario.versionId = row.id;
      this.currentScenario.versionName = row.name;
      this.loading = true;
      this.editScenario()
        .then(() => {
          this.loading = false;
        })
        .catch(() => {
          this.loading = false;
        });
    },
    del(row) {
      this.$alert(this.$t('load_test.delete_threadgroup_confirm') + ' ' + row.name + " ？", '', {
        confirmButtonText: this.$t('commons.confirm'),
        callback: (action) => {
          if (action === 'confirm') {
            this.$get('/api/automation/delete/' + row.id + '/' + this.currentScenario.refId, () => {
              this.$success(this.$t('commons.delete_success'));
              this.getVersionHistory();
            });
          }
        }
      });
    }
  }
}
</script>

<style scoped>
.card-content {
  height: calc(100vh - 200px);
  overflow-y: auto;
}

.ms-scenario-input {
  width: 100%;
}

.ms-debug-div {
  border: 1px #DCDFE6 solid;
  border-radius: 4px;
  margin-right: 0px;
}

.ms-font {
  color: #303133;
  font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
  font-size: 13px;
}

.ms-col-one {
  margin-top: 5px;
}

#fab {
  right: 60px;
  bottom: 120px;
  z-index: 5;
}

/deep/ .el-tree-node__content {
  height: 100%;
  margin-top: 3px;
  vertical-align: center;
}

/deep/ .el-card__body {
  padding: 6px 10px;
}

/deep/ .el-drawer__body {
  overflow: auto;
}

/deep/ .el-step__icon.is-text {
  border: 1px solid;
}

/deep/ .el-drawer__header {
  margin-bottom: 0px;
}

/deep/ .el-link {
  font-weight: normal;
}

/deep/ .el-checkbox {
  color: #303133;
  font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
  font-size: 13px;
  font-weight: normal;
}

/deep/ .el-checkbox__label {
  padding-left: 5px;
}

.head {
  border-bottom: 1px solid #303133;
  color: #303133;
  font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
  font-size: 13px;
}

.ms-tree >>> .el-tree-node__expand-icon.expanded {
  -webkit-transform: rotate(0deg);
  transform: rotate(0deg);
}

.ms-tree >>> .el-tree-node__content > .el-tree-node__expand-icon {
  padding: 3px;
}

.ms-tree >>> .el-icon-caret-right:before {
  padding: 0;
  content: "";
}

.ms-tree >>> .el-tree-node__expand-icon.is-leaf {
  color: transparent;
}

.ms-tree >>> .el-tree-node__expand-icon {
  color: #7C3985;
}

.ms-tree >>> .el-tree-node__expand-icon.expanded.el-icon-caret-right:before {
  color: #7C3985;
  /* content: "\e722";*/
  padding: 0;
  content: "";
}

.ms-sc-variable-header >>> .el-dialog__body {
  padding: 0px 20px;
}

.alt-ico {
  font-size: 15px;
  margin: 5px 10px 0px;
  float: right;
  color: #8c939d;
}

.alt-ico:hover {
  color: black;
  cursor: pointer;
}

.ms-batch-btn {
  margin-left: 5px;
}

.ms-batch-btn:hover {
  cursor: pointer;
  color: #783887;
}

.ms-debug-result {
  margin-top: 3px;
  height: 20px;
  float: right;
}

.ms-message-right {
  margin-right: 10px;
}

.custom-node_e {
  color: #7C3985;
  font-size: 20px;
}

.custom-tree-node-col {
  width: 25px;
  padding: 0px;
  margin-left: 5px;
  vertical-align: center;
}

.custom-tree-node-hide {
  width: 15px;
  padding: 0px;
  vertical-align: center;
}

/deep/ .ms-main-container {
  padding: 5px 5px 5px 10px;
}
</style>
